package com.example.tongyao.system.config;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.tongyao.system.entity.SysFreeAuth;
import com.example.tongyao.system.service.ISysFreeAuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.annotation.Resource;
import java.util.List;

/**
 * 全部功能参考文章：https://blog.csdn.net/qq_29580525/article/details/79317969
 *
 *
 * Security登录配置
 */

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${api.security.path}")
    String apiPath;

    @Resource
    private AuthenticationProvider securityAuthenticationProvider;

    @Resource
    private AuthenticationSuccessHandler securityAuthenticationSuccess;

    @Resource
    private AuthenticationFailureHandler securityAuthenticationFail;


    /**
     * 注入我们自己定义的用户信息获取对象
     */
    @Resource
    private UserDetailsService userDetailService;

    @Value("${api.path.model}")
    String model;

    @Value("${login.auth.type}")
    String loginAuthType;


    @Resource
    private ISysFreeAuthService iSysFreeAuthService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        String[] path = null;
        if(model.equals("config")){
            path = apiPath.split(",");
        }else if(model.equals("database")){
            LambdaQueryWrapper<SysFreeAuth> sysFreeAuthLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysFreeAuthLambdaQueryWrapper.eq(SysFreeAuth::getPathType,"free_login");
            sysFreeAuthLambdaQueryWrapper.eq(SysFreeAuth::getDelFlag,"1");
            List<SysFreeAuth> sysFreeAuthList =iSysFreeAuthService.list(sysFreeAuthLambdaQueryWrapper);

            String free_login_path = "";
            for(SysFreeAuth sysFreeAuth : sysFreeAuthList){
                free_login_path = free_login_path + sysFreeAuth.getPathAddress()+",";
            }
            path = free_login_path.split(",");
        }else{
            throw new RuntimeException("读取权限路径使用模式出错，请检查是config或database！");
        }


        if(loginAuthType.equals("to_menu")){
            http
                    .formLogin().loginPage("/defaultMsg").loginProcessingUrl("/login")

                    //登录成功后调用的
                    .successHandler(securityAuthenticationSuccess)
                    //登录失败后调用的
                    .failureHandler(securityAuthenticationFail)
                    .permitAll()
                    .and().exceptionHandling().accessDeniedPage("/unauthorized")
                    .and()
                    .authorizeRequests()

                    //免登录访问
                    .antMatchers(path).permitAll()

                    //使用静态注解形式管理权限
                    .anyRequest().authenticated()

                    .and().logout().logoutSuccessHandler(new SecurityLogoutSuccess())
                    .and()
                    .csrf().disable();
        }else if(loginAuthType.equals("to_interface")){
            http
                    .formLogin().loginPage("/defaultMsg").loginProcessingUrl("/login")

                    //登录成功后调用的
                    .successHandler(securityAuthenticationSuccess)
                    //登录失败后调用的
                    .failureHandler(securityAuthenticationFail)
                    .permitAll()
                    .and().exceptionHandling().accessDeniedPage("/unauthorized")
                    .and()
                    .authorizeRequests()

                    //免登录访问
                    .antMatchers(path).permitAll()

                    //使用动态权限形式管理权限
                    .anyRequest().access("@SecurityPermission.addPermission(request,authentication)")    //必须经过认证以后才能访问

                    .and().logout().logoutSuccessHandler(new SecurityLogoutSuccess())
                    .and()
                    .csrf().disable();
        }else{
            throw new RuntimeException("登录类型出错！请查看配置文件中${login.auth.type}值是否是 to_interface 或 to_menu ！");
        }

    }


    /**
     * 成功之后调用的 provider
     * @param auth
     * @throws Exception
     */
    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(securityAuthenticationProvider);
    }

}